#pragma once
#include <QByteArray>
#include <QDataStream>
#include <QMap>
#include <QAtomicInteger>
using namespace std;

class netDataManager;

//PackInfo
struct PackInfo
{
	PackInfo();
	
	ushort addr;
	uchar head2;
	uchar cmd;
	uchar len;

	int headLength() const;
	int bodyLength() const;
	
	bool Pack(QByteArray &buffer) const;
	bool UnPack(QByteArray &buffer,int offset);	
};

class NetPack
{
public:
	NetPack();
	virtual ~NetPack();
	
    virtual int type() const = 0 ;
	virtual bool pack(QByteArray &buffer) const = 0 ;
	virtual bool unPack(const QByteArray &buffer) = 0;	

	PackInfo info;

private:
	friend netDataManager;	
};

typedef NetPack *(*CreatePackFunc)();
class NetPackManager
{
public:
	static NetPackManager *instance();
	NetPackManager();

	template<class T>
	void registPack()
	{		
		int id = T::NetType;
		Q_ASSERT(!mPackFactory.contains(id));		
		mPackFactory[id] = T::netPackCreate;
	}
	NetPack *createPack(int id);
	int genSeq();

protected:
	QMap<int, CreatePackFunc> mPackFactory;
	QAtomicInteger<unsigned int> mPackSeq;
};
typedef QSharedPointer<NetPack> NetPackPtr;

#define DECLAR_PACK(Class,ClassType) \
	static NetPack *netPackCreate(){ return new Class();} \
	static const int NetType = ClassType; \
	virtual int type() const{ return Class::NetType; }
